<?php

namespace App\Http\Proxy;
use App\Seller;
use GuzzleHttp\Exception\RequestException;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\UnauthorizedException;
use Laravel\Passport\Passport;

/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2017/10/25 0025
 * Time: 23:02
 */
class TokenProxy
{
    protected $http;

    /**
     * TokenProxy constructor.
     * @param $http
     */
    public function __construct(\GuzzleHttp\Client $http)
    {
        $this->http = $http;
    }

    /**
     * 这里暂时用默认的sessionGuard去实现登录逻辑
     * @param $verify
     * @param $password
     * @return $this|\Illuminate\Http\JsonResponse
     */
    public function login($verify, $password)
    {
        if(!empty(request('scope'))){
            $scope = explode(',',request('scope'));
            foreach ($scope as $v){
                if(!in_array($v,Passport::scopeIds())){
                    return response()->json([
                        'status' => 'scope error',
                        'status_code' => 421,
                        'msg' => '作用域不存在'
                    ],421);
                }

                if(explode('_',$v)[0].'s' != request('provider')){
                    return response()->json([
                        'status' => 'scope illegal',
                        'status_code' => 421,
                        'msg' => '非法请求作用域'
                    ],421);
                }
            }

            $scope = implode(' ',$scope);
            if(stripos($scope,'full_authority') !== false){
                $scope = '*';
            }
        }

        $provider = request('provider','users');
        switch ($provider){
            case 'sellers':
                if(empty($verify)){
                    return response()->json([
                        'status' => 'mobile empty',
                        'status_code' => 421,
                        'msg' => '手机号不能为空'
                    ],421);
                }
                break;
            case 'agencys':
                if(empty($verify)){
                    return response()->json([
                        'status' => 'mobile empty',
                        'status_code' => 421,
                        'msg' => '手机号不能为空'
                    ],421);
                }
                break;
            case 'admins':
                if(empty($verify)){
                    return response()->json([
                        'status' => 'username empty',
                        'status_code' => 421,
                        'msg' => '用户名不能为空'
                    ],421);
                }
                break;
            case 'users':
            default:
                if(empty($verify)){
                    return response()->json([
                        'status' => 'wechat_unionid empty',
                        'status_code' => 421,
                        'msg' => 'unionid不能为空'
                    ],421);
                }
                break;
        }

        try{
            //event(new UserLogin());
            $respond = $this->proxy('password', [
                'username' => $verify,
                'password' => $password,
                'provider' => $provider,
                'scope' => $scope??'',
            ]);

            return $respond;
        }catch (RequestException $exception){
            if ($exception->getCode() == 401) {
                return response()->json([
                    'status' => 'login error',
                    'status_code' => 401,
                    'msg' => '登录信息不匹配'
                ],401);
            }
            throw new UnauthorizedException('请求失败，服务器错误');
        }
    }


    public function loginByWechatUnionid($unionid)
    {

    }


    public function loginByWechatOpenid($openid)
    {

    }

    /**
     * 目前只做了密码模式获取token和刷新token
     * @param $grantType
     * @param array $data
     * @return \Illuminate\Http\JsonResponse
     */
    public function proxy($grantType, array $data = [])
    {
        switch ($grantType){
            case 'personal_access':
                $param = [
                    'client_id'     => env('PERSONAL_CLIENT_ID'),
                    'client_secret' => env('PERSONAL_CLIENT_SECRET'),
                    'grant_type'    => $grantType
                ];
                break;
            case 'password':
            default:
                $param = [
                    'client_id'     => env('PASSPORT_CLIENT_ID'),
                    'client_secret' => env('PASSPORT_CLIENT_SECRET'),
                    'grant_type'    => $grantType
                ];
                break;
        }

        $data = array_merge($data, $param);

        $website = $_SERVER['HTTP_HOST'];
        $protocol = (isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] === 443) ? 'https:' : 'http:';
        $oauthUrl = $protocol . '//' . $website;

        $response = $this->http->post($oauthUrl . '/api/oauth/token', ['form_params' => $data
        ]);
        $token = json_decode((string)$response->getBody(), true);

        return response()->json([
            'token'=>$token['access_token'],
            'refresh_token'=>!empty($token['refresh_token'])?$token['refresh_token']:'',
            'expires_in' => $token['expires_in'],
            'status' => 'success',
            'status_code' => 200
        ]);
    }

    /**
     * @return \Illuminate\Http\JsonResponse
     */
    public function logout()
    {
        $user = auth()->guard('api')->user();
        $accessToken = $user->token();
        app('db')->table('oauth_refresh_tokens')
                         ->where('access_token_id', $accessToken->id)
                         ->update([
                             'revoked' => true
                         ]);

        $accessToken->revoke();

        return response()->json([
            'status' => 'success',
            'status_code' => 200,
            'message' => 'logout success'
            ]
        ,200);
    }

    /**
     * @param $refreshToken
     * @return \Illuminate\Http\JsonResponse
     */
    public function refresh($refreshToken)
    {
        return $this->proxy('refresh_token',
            ['refresh_token' =>(string) $refreshToken]);
    }
}